import base64
import json

import aiohttp
import aiohttp_socks
import requests
from loguru import logger
from tenacity import retry, stop_after_attempt, wait_fixed

from common import config, utils


class Website:
    def __init__(self):
        self.default_headers = {
            "accept": "*/*",
            "accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
            "content-type": "text/plain;charset=UTF-8",
            "origin": "https://app.getgrass.io",
            "priority": "u=1, i",
            "referer": "https://app.getgrass.io/",
            "sec-ch-ua": '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
            "sec-ch-ua-mobile": "?1",
            "sec-ch-ua-platform": '"Windows"',
            "sec-fetch-dest": "empty",
            "sec-fetch-mode": "cors",
            "sec-fetch-site": "same-site",
            "user-agent": config.DEFAULT_USER_AGENT
        }
    async def login(self, username, password, proxy_ip, proxy_port, proxy_username, proxy_password):
        try:
            return await self.login_with_proxy(username, password, proxy_ip, proxy_port, proxy_username, proxy_password)
        except Exception as e:
            logger.error(f"用户{username}登录获取user_id异常:{e}")
            return await self.login_no_proxy(username, password)
    async def login_with_proxy(self, username, password, proxy_ip, proxy_port, proxy_username, proxy_password):
        url = "https://api.getgrass.io/login"
        data = {
            "username": username,
            "password": password
        }
        socks5_proxy_url = f"socks5://{proxy_username}:{proxy_password}@{proxy_ip}:{proxy_port}"
        socks5_proxy = aiohttp_socks.ProxyConnector.from_url(socks5_proxy_url)
        async with aiohttp.ClientSession(connector=socks5_proxy) as session:
            async with session.post(url, headers=self.default_headers, json=data) as response:
                if response is None or response.status != 200:
                    return None
                text = await response.text()
                return json.loads(text)["result"]["data"]
    @retry(stop=stop_after_attempt(3), wait=wait_fixed(1))
    async def login_no_proxy(self, username, password):
        url = "https://api.getgrass.io/login"
        data = {
            "username": username,
            "password": password
        }
        try:
            response = requests.post(url, headers=self.default_headers, json=data)
            if response is None or response.status_code != 200:
                return None
            text = response.text
            return json.loads(text)["result"]["data"]
        except requests.RequestException as e:
            print(f"请求出现异常: {e}")
            return None

    async def auth_client(self, client_key):
        url = f"http://124.71.80.94:5000/test_client?mac={utils.get_mac_address()}&key={client_key}&key=1"
        try:
            response = requests.get(url, headers=self.default_headers)
            if response is None or response.status_code != 200:
                return None
            return response.content
        except requests.RequestException as e:
            print(f"请求出现异常: {e}")
            return None
    async def get_client_ip(self, proxy_ip, proxy_port, proxy_username, proxy_password):
        url = "https://api.bigdatacloud.net/data/client-ip"
        socks5_proxy_url = f"socks5://{proxy_username}:{proxy_password}@{proxy_ip}:{proxy_port}"
        socks5_proxy = aiohttp_socks.ProxyConnector.from_url(socks5_proxy_url)
        async with aiohttp.ClientSession(connector=socks5_proxy) as session:
            async with session.post(url, headers=self.default_headers) as response:
                if response is None or response.status != 200:
                    return None
                text = await response.text()
                return json.loads(text)
    async def handle_http_request(self, message):
        try:
            params = message['data']
            request_options = {
                'headers': params['headers'],
            }
            async with aiohttp.ClientSession() as session:
                if 'body' in params:
                    fetch_url = f"data:application/octet-stream;base64,{params['body']}"
                    async with session.get(fetch_url) as fetch_resp:
                        request_options['data'] = await fetch_resp.read()
                async with session.request(
                        method=params['method'],
                        url=params['url'],
                        **request_options
                ) as response:
                    headers = {
                        "connection": response.headers.get("Connection", "keep-alive"),
                        "content-length": response.headers.get("Content-Length", ""),
                        "content-type": response.headers.get("Content-Type", ""),
                        "date": response.headers.get("Date", ""),
                        "etag": response.headers.get("ETag", ""),
                        "keep-alive": response.headers.get("Keep-Alive", ""),
                        "x-powered-by": response.headers.get("X-Powered-By", "")
                    }

                    body = await response.read()
                    base64_body = base64.b64encode(body).decode('utf-8')

                    return {
                        'id': message['id'],
                        'origin_action': 'HTTP_REQUEST',
                        'result': {
                            'url': str(response.url),
                            'status': response.status,
                            'status_text': response.reason,
                            'headers': headers,
                            'body': base64_body,
                        }
                    }
        except Exception as e:
            logger.error(f"处理HTTP_REQUEST消息异常:{e}")
            return {
                'id': message['id'],
                'origin_action': 'HTTP_REQUEST',
                'result': {
                    'url': message['data']['url'],
                    'status': 400,
                    'status_text': 'Bad Request',
                    'headers': {},
                    'body': '',
                }
            }
website = Website()